<script setup lang="ts">
import { reactive, ref, watch } from "vue";
import { RegionItem, queryRegionInfo } from "@/api/modules/org/query/query-region";
import { CascaderProps } from "element-plus";

type CascaderAddressProps = {
  /**是否显示详细地址 */
  showDetailAddress?: boolean;
  value?: number[];
  detailAddress?: string;
  props?: CascaderProps;
  disabled?: boolean;
};

const emit = defineEmits<{
  (e: "update:value", modelValue: number[]): void;
  (e: "update:detailAddress", detailAddress?: string): void;
}>();

const props = withDefaults(defineProps<CascaderAddressProps>(), {
  showDetailAddress: false,
  props: () => {
    return { label: "name", value: "code" };
  }
});

const CascaderRef = ref();

const CascaderAddressState = reactive({
  props: props.props,
  data: [] as RegionItem[],
  modelValue: props.value as number[], //存放省市区坐标
  detailAddress: props.detailAddress, //详细地址
  loadData() {
    queryRegionInfo().then(res => {
      CascaderAddressState.data = CascaderAddressState.transformData(res.data);
    });
  },
  transformData(data: RegionItem[]) {
    //组织省市级数据map
    const provinceDataMap: Map<number, RegionItem> = new Map();
    const cityDataMap: Map<number, RegionItem> = new Map();
    const districtData: RegionItem[] = [];
    data.forEach(item => {
      if (item.level === "province") {
        provinceDataMap.set(item.code, item);
      } else if (item.level === "city") {
        cityDataMap.set(item.code, item);
      } else if (item.level === "district") {
        districtData.push(item);
      }
    });

    //将县区数据放到市区里面
    districtData.forEach(item => {
      if (item.pcode) {
        const cityItem = cityDataMap.get(item.pcode);
        if (cityItem) {
          if (!cityItem.children) cityItem.children = [];
          cityItem.children.push(item);
        }
      }
    });
    //
    cityDataMap.forEach(item => {
      if (item.pcode) {
        const provinceItem = provinceDataMap.get(item.pcode);
        if (provinceItem) {
          if (!provinceItem.children) provinceItem.children = [];
          provinceItem.children.push(item);
        }
      }
    });
    const regionItemArr: RegionItem[] = [];
    provinceDataMap.forEach(item => regionItemArr.push(item));
    return regionItemArr;
  },
  getCheckedNodes(flag: boolean) {
    return CascaderRef.value.getCheckedNodes(flag);
  },
  getAddressText() {
    const node = CascaderAddressState.getCheckedNodes(false)[0];
    const pathLabels = node.pathLabels as string[];
    let address = "";
    pathLabels.forEach(label => (address += label));
    return address;
  }
});

CascaderAddressState.loadData();

defineExpose({
  getCheckedNodes: (flag: boolean) => CascaderAddressState.getCheckedNodes(flag),
  /**获取省市区地址 */
  getAddressText: () => CascaderAddressState.getAddressText(),
  /**获取全量地址 */
  getFullAddressText() {
    let fullAddress = CascaderAddressState.getAddressText();
    if (props.showDetailAddress && CascaderAddressState.detailAddress) fullAddress += CascaderAddressState.detailAddress;
    return fullAddress;
  }
});

watch(
  () => props.value,
  val => {
    CascaderAddressState.modelValue = val || [];
  }
);

watch(
  () => CascaderAddressState.modelValue,
  val => {
    emit("update:value", val);
  }
);

watch(
  () => props.detailAddress,
  val => {
    CascaderAddressState.detailAddress = val;
  }
);
watch(
  () => CascaderAddressState.detailAddress,
  val => {
    emit("update:detailAddress", val);
  }
);
</script>
<template>
  <div class="jxtech-cascader-address-container">
    <el-cascader
      style="width: 100%"
      ref="CascaderRef"
      :options="CascaderAddressState.data"
      :props="CascaderAddressState.props"
      clearable
      filterable
      :disabled="props.disabled"
      v-model:model-value="CascaderAddressState.modelValue"
    />
    <div class="jxtech-cascader-full-address" v-if="showDetailAddress">
      <el-input
        :disabled="props.disabled"
        v-model="CascaderAddressState.detailAddress"
        type="textarea"
        :rows="3"
        placeholder="请输入详细地址"
      />
    </div>
  </div>
</template>
<style scoped lang="scss">
.jxtech-cascader-address-container {
  display: inline-block;
  width: 100%;
}
.jxtech-cascader-full-address {
  margin-top: 12px;
}
</style>
